﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Windows.Forms;
using fastJSON;
using gtasks.Auth;
using gtasks.Model;
using gtasks.Utils;
using pub.GUI;
using pub.NET20Fix;

namespace gtasks
{
    internal class TaskManager
    {
        public static TaskManager Instance = new TaskManager();

        private Action<Tasks> _callback;
        private WebRequest _request;

        public event Action<Exception> OnException;

        public void LoadTasks(string taskListId, Action<Tasks> callback)
        {
            _callback = callback;
            var url = "https://www.googleapis.com/tasks/v1/lists/" + taskListId +
                    "/tasks?fields=items(id%2Cparent%2Ctitle%2Cnotes%2Cdue%2Cstatus%2Ccompleted)";

            AuthManager.Instance.AuthExecute(() => {
                var req = HttpUtils.CreateRequest(url);
                SetRequest(req);
                return req;
            }, req => req.BeginGetResponse(GetResponseCallback, req));
        }

        public Tasks LoadTasks(string taskListId, string token)
        {
            var url = "https://www.googleapis.com/tasks/v1/lists/" + taskListId +
                    "/tasks?fields=items(id%2Cparent%2Ctitle%2Cnotes%2Cdue%2Cstatus%2Ccompleted)";
            var req = HttpUtils.CreateRequest(url, token);
            SetRequest(req);
            var rsp = req.GetResponse();
            string text;
            using (var reader = new StreamReader(rsp.GetResponseStream()))
            {
                text = reader.ReadToEnd();
            }
            rsp.Close();
            req.Abort();
            var tasks = JSON.Instance.ToObject<Tasks>(text);
            if (tasks.items == null)
            {
                tasks.items = new List<Task>();
            }
            return tasks;
        }

        private void SetRequest(HttpWebRequest req)
        {
            try
            {
                if (_request != null)
                {
                    _request.Abort();
                }
            }
            catch
            {
                // ignore
            }
            _request = req;
        }

        private void GetResponseCallback(IAsyncResult ar)
        {
            var req = (HttpWebRequest) ar.AsyncState;
            WebResponse rsp = null;
            try
            {
                rsp = req.EndGetResponse(ar);
            }
            catch (Exception e)
            {
                AsyncUtils.FireOnException(OnException, e);
                return;
            }
            string text;
            using (var reader = new StreamReader(rsp.GetResponseStream()))
            {
                text = reader.ReadToEnd();
            }
            rsp.Close();
            var tasks = JSON.Instance.ToObject<Tasks>(text);
            if (tasks.items == null)
            {
                tasks.items = new List<Task>();
            }
            _callback(tasks);
        }

        public void AbortProcessing()
        {
            AuthManager.Instance.AbortProcessing();
            try
            {
                if(_request != null)
                {
                    _request.Abort();
                }
            }
            catch
            {
                // ignore
            }
        }

        public Task Insert(string taskListId, Task task, string parentId, string prevId,
                           string token)
        {
            Debug.Print("@@@@@ [INSERT] task: " + task.title + ", parentId: " + parentId + 
                ", prevId: " + prevId);

            var url = "https://www.googleapis.com/tasks/v1/lists/" + taskListId + "/tasks";
            var qs = "?fields=id%2Cparent%2Ctitle%2Cnotes%2Cdue%2Cstatus%2Ccompleted";
            if (!string.IsNullOrEmpty(parentId))
            {
                qs += "&parent=" + parentId;
            }
            if (!string.IsNullOrEmpty(prevId))
            {
                qs += "&previous=" + prevId;
            }
            url += qs;

            var req = HttpUtils.CreateRequest(url, token);
            req.Method = "POST";
            req.ContentType = "application/json";
            var paramMap = new Dictionary<string, object> {
                    {"title", task.title},
                    {"notes", task.notes},
                    {"status", task.status}
            };
            if (task.due != DateTime.MinValue)
            {
                paramMap["due"] = task.due;
            }
            var completed = task.status == "completed";
            if (completed && task.completed != DateTime.MinValue)
            {
                paramMap["completed"] = task.completed;
            }
            var json = JSON.Instance.ToJSON(paramMap);

            using (var sw = new StreamWriter(req.GetRequestStream()))
            {
                sw.Write(json);
                sw.Flush();
                sw.Close();
            }

            var rsp = req.GetResponse();
            string text;
            using (var reader = new StreamReader(rsp.GetResponseStream()))
            {
                text = reader.ReadToEnd();
            }
            rsp.Close();
            var resultTask = JSON.Instance.ToObject<Task>(text);
            return resultTask;
        }

        public void Move(string taskListId, string taskId, string parentId, string prevId, string token)
        {
            Debug.Print("@@@@@ [MOVE] taskId: " + taskId + ", parentId: " + parentId + ", prevId: " + prevId);

            var url = "https://www.googleapis.com/tasks/v1/lists/" + taskListId +
                "/tasks/" + taskId + "/move";
            var qs = "?fields=id";
            if (!string.IsNullOrEmpty(parentId))
            {
                qs += "&parent=" + parentId;
            }
            if (!string.IsNullOrEmpty(prevId))
            {
                qs += "&previous=" + prevId;
            }
            url += qs;

            var req = HttpUtils.CreateRequest(url, token);
            req.Method = "POST";
            req.ContentLength = 0;
            
            HttpWebResponse rsp;
            try
            {
                rsp = req.GetResponse() as HttpWebResponse;
            }
            catch (Exception e)
            {
                //todo: unknown exception handling
                Console.WriteLine("?");
                throw;
            }
            string text;
            using (var reader = new StreamReader(rsp.GetResponseStream()))
            {
                text = reader.ReadToEnd();
            }
            rsp.Close();
            return;
        }

        public void Delete(string taskListId, string taskId, string token)
        {
            Debug.Print("@@@@@ [DELETE] taskId: " + taskId);

            var url = "https://www.googleapis.com/tasks/v1/lists/" + taskListId +
                "/tasks/" + taskId;

            var req = HttpUtils.CreateRequest(url, token);
            req.Method = "DELETE";
            var rsp = req.GetResponse() as HttpWebResponse;
            var statusCode = rsp.StatusCode;
            rsp.Close();
            req.Abort();
//            if (statusCode == HttpStatusCode.NoContent)
//            {
//                return;
//            }
//            string text;
//            using (var reader = new StreamReader(rsp.GetResponseStream()))
//            {
//                text = reader.ReadToEnd();
//            }
        }
    }
}